
import {
    _decorator, Component, view, ResolutionPolicy, screen, Canvas, assetManager, log, AssetManager,
    Prefab, instantiate, game, director, tween, Tween
} from 'cc';
import { LayerBase, LayerCfg } from './LayerBase';
const { ccclass, property } = _decorator;

@ccclass('App')
export class App extends Component {
    static instance: App
    static cvsUI: Canvas

    async start() {
        App.instance = this
        this.fitScreen()

        game.addPersistRootNode(this.node)

        App.asyncGetBundle('Public')

        App.changeScene('Test', 'Test', (num, total) => {
        })

    }

    fitScreen() {
        const winSize = screen.windowSize
        const designSize = view.getDesignResolutionSize()
        if (winSize.width / winSize.height > designSize.width / designSize.height) {
            view.setDesignResolutionSize(designSize.width, designSize.height, ResolutionPolicy.FIXED_HEIGHT)
        }
        else {
            view.setDesignResolutionSize(designSize.width, designSize.height, ResolutionPolicy.FIXED_WIDTH)
        }
    }

    // 也可以单场景
    static changeScene(sceneName: string, bundleName: string, onProgress?: (num: number, total: number) => void) {
        return new Promise<void>(async (resolve, reject) => {
            const bundle = await App.asyncGetBundle(bundleName)

            bundle.loadScene(sceneName, (num, total) => {
                onProgress && onProgress(num, total)
            }, function (err, scene) {
                director.runScene(scene);
                resolve()
            });
        })
    }

    static showLayer(config: LayerCfg, data: any) {
        return new Promise<any>(async (resolve, reject) => {
            const bundle = await App.asyncGetBundle(config.bundleName)
            const prefab = await App.asyncLoadPrefab(bundle, config.prefabName)
            prefab.addRef()
            log('refCount', prefab.refCount)
            const node = instantiate(prefab)
            node.parent = App.cvsUI.node

            const script = node.getComponent(config.prefabName) as LayerBase
            script.closeCallback = resolve
            script.prefab = prefab
            script.init(data)
        })
    }

    static asyncGetBundle(bundleName: string) {
        return new Promise<AssetManager.Bundle>((resolve, reject) => {
            const bundle = assetManager.getBundle(bundleName)
            if (bundle) {
                resolve(bundle)
                return
            }
            log('loadBundle', bundleName)
            assetManager.loadBundle(bundleName, (err, bundle) => {
                err ? reject(err) : resolve(bundle)
            })
        })
    }

    static asyncLoadPrefab(bundle: AssetManager.Bundle, prefabName: string) {
        return new Promise<Prefab>((resolve, reject) => {
            bundle.load(prefabName, Prefab, (err, prefab) => {
                err ? reject(err) : resolve(prefab)
            })
        })
    }

    static asyncTween<T>(target: T, t: Tween<T>) {
        return new Promise((resolve) => {
            tween(target).then(t).call(resolve).start();
        })
    }
}
